package com.gopay.checkorder.service.impl.micro;

import java.math.BigDecimal;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.manager.BankOrderManager;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.task.BankCountDownLatch;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.MicroPayConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.MicroPayBaseMessage;
import com.gopay.common.domain.bank.dayend.BaseDayendEntry;
import com.gopay.common.domain.bank.wechat.micro.res.MicroQueryResMsg;
import com.gopay.common.domain.bank.wechat.micro.res.MicroRefundQueryResItem;
import com.gopay.common.domain.bank.wechat.micro.res.MicroRefundQueryResMsg;
import com.gopay.common.domain.cashier.BankCardType;
import com.gopay.common.domain.cps.vo.CheckOrderResult;
import com.gopay.common.domain.cps.vo.InAccInfo;
import com.gopay.remote.bank.MicroPayInteractRemoteService;

/**
 * 小额免密 支付、退款订单查询
 * 
 * @ClassName: CheckOrderMicroPayCiticImpl
 * @author w_jiqing
 * @date 2017年5月27日 下午2:05:17
 */
public class CheckOrderMicroPayCiticImpl implements BankOrderService {

    private final static Logger logger = LoggerFactory.getLogger(CheckOrderMicroPayCiticImpl.class);

    @Resource(name = "microPayClient")
    private MicroPayInteractRemoteService microPayClient;

    @Resource(name = "bankOrderManager")
    protected BankOrderManager bankOrderManager;

    @Resource(name = "cpsGeneralMainOrderQueryManager")
    private CpsGeneralMainOrderQueryManager mainOrderQuery;

    @Override
    public CheckOrderResult checkOrder(BankOrder bankOrder, String target) {
        /**
         * 对单返回对象
         */
        CheckOrderResult checkOrderResult = new CheckOrderResult();
        checkOrderResult.setSuccess(false);
        checkOrderResult.setOrderId(bankOrder.getOrderId());

        MicroPayBaseMessage message = new MicroPayBaseMessage();

        message.setOrderId(bankOrder.getOrderId()); // 国付宝系统订单号
        message.setBankOrderId(bankOrder.getOutOrderId());// 上送银行单号
        message.setBankIntrChann(BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()));// 银行通道码
        message.setBankBusProd(BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));// 银行业务产品码
        message.setBank(bankOrder.getBankCode());// 微信、支付宝

        Result result = new Result();
        try {
            if (BisBankBusinessProd._12.value.equals(message.getBankBusProd().value)) {
                // 退款订单处理
                message.setTkOriBankOrderId(bankOrder.getOriOutOrderId());
                result = microPayClient.refundQuery(message);
                return refundCheckOrder(result, bankOrder);
            } else if (BisBankBusinessProd._26.value.equals(message.getBankBusProd().value)) {
                BankOrder oriBankOrder = bankOrderManager.getByGopayOutOrderId(bankOrder.getOriOutOrderId());
                message.setCzOriBankOrderId(bankOrder.getOriOutOrderId());
                message.setCzOriOrderId(oriBankOrder.getOrderId());
                result = microPayClient.reverseQuery(message);
                return reverseCheckOrder(result, bankOrder, target);
            } else {
                // 支付订单处理
                result = microPayClient.orderQuery(message);
            }
            if (result == null || !result.isSuccess()) {
                logger.error("microPayClient fail.");
                if (result == null || ProcCodeConstants.PROC_CODE_100F1002.equals(result.getResultCode())
                        || ProcCodeConstants.PROC_CODE_100E6063.equals(result.getResultCode())) {
                    BankCountDownLatch.failIncrease(bankOrder.getBankCode());
                }
                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
                checkOrderResult.setErrMsg("系统返回对账结果为空");
                return checkOrderResult;
            }
            MicroQueryResMsg res = (MicroQueryResMsg) result.getDefaultModel();

            if (res == null) {
                /**
                 * 查询结果为空
                 */
                logger.error("fail:orderId:" + bankOrder.getOrderId() + " errcode:"
                        + ProcCodeConstants.PROC_CODE_100E6022 + " err:bis query is null.");
                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
                checkOrderResult.setErrMsg("返回对账结果为空");
                return checkOrderResult;
            }
            if (res.isSuccess()) {
                if (MicroPayConstants.MICRO_RESULT_CODE_SUCCESS.equals(res.getResult_code())) {
                    // 业务成功
                    String tradeState = res.getTrade_state();
                    if (MicroPayConstants.MICRO_QUERY_SUCCESS.equals(tradeState)) {
                        checkOrderResult.setSuccess(true);
                        InAccInfo accInfo = new InAccInfo();
                        accInfo.setOrderId(bankOrder.getOrderId());
                        accInfo.setAmount(new BigDecimal(res.getTotal_fee()).divide(new BigDecimal(100)));
                        accInfo.setRetCode("00");
                        accInfo.setCardType(BankCardType.Unknown.toString());
                        checkOrderResult.setAccInfo(accInfo);
                        logger.error("小额免密支付订单：" + message.getOrderId() + "，交易成功" + "交易状态：" + tradeState + ",交易状态描述:"
                                + res.getTrade_state_desc());
                    } else if (MicroPayConstants.MICRO_QUERY_PAYERROR.equals(tradeState)) {
                        InAccInfo accInfo = new InAccInfo();
                        accInfo.setOrderId(bankOrder.getOrderId());
                        accInfo.setAmount(new BigDecimal(res.getTotal_fee()).divide(new BigDecimal(100)));
                        accInfo.setRetCode("01");
                        accInfo.setCardType(BankCardType.Unknown.toString());
                        checkOrderResult.setAccInfo(accInfo);
                        checkOrderResult.setBankFailure(true);
                        checkOrderResult.setErrMsg("小额免密查询返回交易失败！");
                        logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，交易失败" + "交易状态：" + tradeState + ",交易状态描述:"
                                + res.getTrade_state_desc());
                    } else if (MicroPayConstants.MICRO_QUERY_NOTPAY.equals(tradeState)) {
                        checkOrderResult.setErrMsg("小额免密订单进行中！");
                        logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，交易处理中" + "交易状态：" + tradeState + ",交易状态描述:"
                                + res.getTrade_state_desc());
                    } else if (MicroPayConstants.MICRO_QUERY_REFUND.equals(tradeState)) {
                        checkOrderResult.setErrMsg("小额免密订单转入退款！");
                        logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，交易转入退款" + "交易状态：" + tradeState
                                + ",交易状态描述:" + res.getTrade_state_desc());
                    } else if (MicroPayConstants.MICRO_QUERY_CLOSED.equals(tradeState)) {
                        checkOrderResult.setErrMsg("小额免密订单已关闭！");
                        logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，交易已关闭" + "交易状态：" + tradeState + ",交易状态描述:"
                                + res.getTrade_state_desc());
                    } else if (MicroPayConstants.MICRO_QUERY_USERPAYING.equals(tradeState)) {
                        checkOrderResult.setErrMsg("小额免密订单用户支付中！");
                        logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，交易用户支付中" + "交易状态：" + tradeState
                                + ",交易状态描述:" + res.getTrade_state_desc());
                    } else {
                        checkOrderResult.setErrMsg("小额免密返回交易状态不明");
                        logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，返回交易状态不明，系统暂不处理" + "返回码："
                                + res.getTrade_state());
                    }
                } else {
                    checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
                    checkOrderResult.setErrMsg("系统返回对账结果为空");
                    logger.error("支付订单：" + bankOrder.getOrderId() + "，查询失败" + "err_code：" + res.getErr_code()
                            + "。错误信息为：" + res.getErr_msg());
                }
            } else {
                checkOrderResult.setErrMsg("验签失败");
                logger.error("小额免密支付订单：" + bankOrder.getOrderId() + "，验签失败" + "status：" + res.getStatus() + "。返回信息为："
                        + res.getMessage());
            }
        } catch (Exception e) {
            logger.error("microPayClient fail.", e);
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
            checkOrderResult.setErrMsg("小额免密对账异常");
            return checkOrderResult;
        }
        return checkOrderResult;

    }

    /**
     * 冲正订单对账处理
     * 
     * @param result
     * @param bankOrder
     * @return
     * @author w_jiqing
     */
    public CheckOrderResult reverseCheckOrder(Result result, BankOrder bankOrder, String target) {
        CheckOrderResult checkOrderResult = new CheckOrderResult();
        checkOrderResult.setSuccess(false);
        if (result == null || !result.isSuccess()) {
            logger.error("microPayClient fail.");
            if (result == null || ProcCodeConstants.PROC_CODE_100F1002.equals(result.getResultCode())
                    || ProcCodeConstants.PROC_CODE_100E6063.equals(result.getResultCode())) {
                BankCountDownLatch.failIncrease(bankOrder.getBankCode());
            }
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
            checkOrderResult.setErrMsg("系统返回对账结果为空");
            return checkOrderResult;
        }
        MicroQueryResMsg res = (MicroQueryResMsg) result.getDefaultModel();
        if (res == null) {
            /**
             * 查询结果为空
             */
            logger.error("fail:orderId:" + bankOrder.getOrderId() + " errcode:" + ProcCodeConstants.PROC_CODE_100E6022
                    + " err:bis query is null.");
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
            checkOrderResult.setErrMsg("返回对账结果为空");
            return checkOrderResult;
        }

        BankOrder oriBankOrder = bankOrderManager.getByGopayOutOrderId(bankOrder.getOriOutOrderId());
        if (oriBankOrder == null || StringUtils.isBlank(bankOrder.getOrderId())) {
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5060);
            logger.error("bankOrder is null or orderId is null." + bankOrder.toString());
            return checkOrderResult;
        }
        String ordreStatus = oriBankOrder.getOrderStatus();

        if (res.isSuccess()) {
            if (MicroPayConstants.MICRO_RESULT_CODE_SUCCESS.equals(res.getResult_code())) {
                // 业务成功
                String tradeState = res.getTrade_state();

                if (MicroPayConstants.MICRO_QUERY_REVOKED.equals(tradeState)
                        || MicroPayConstants.MICRO_QUERY_CLOSED.equals(tradeState)
                        || MicroPayConstants.MICRO_QUERY_REFUND.equals(tradeState)) {
                    // 订单已冲正
                    if (BankOrderStatus.BANK_CALL_SUCCESS.equals(ordreStatus)
                            || BankOrderStatus.AUTO_CHECK_SUCCESS.equals(ordreStatus)
                            || BankOrderStatus.CHECK_SUCCESS.equals(ordreStatus)) {
                        // 支付成功的订单发起的冲正交易，并且冲正成功
                        checkOrderResult.setSuccess(true);
                        InAccInfo accInfo = new InAccInfo();
                        accInfo.setOrderId(bankOrder.getOrderId());
                        accInfo.setAmount(bankOrder.getSendBankAmt());
                        accInfo.setRetCode("00");
                        accInfo.setCardType(BankCardType.Unknown.toString());
                        checkOrderResult.setAccInfo(accInfo);
                    } else {
                        bankOrderManager.updateSuccess(bankOrder, target);
                    }
                    logger.error("小额免密冲正订单：" + bankOrder.getOrderId() + ",原支付订单：" + oriBankOrder.getOrderId() + "，交易成功"
                            + "交易状态：" + tradeState + ",交易状态描述:" + res.getTrade_state_desc());
                } else {
                    if (BankOrderStatus.BANK_CALL_SUCCESS.equals(ordreStatus)
                            || BankOrderStatus.AUTO_CHECK_SUCCESS.equals(ordreStatus)
                            || BankOrderStatus.CHECK_SUCCESS.equals(ordreStatus)) {
                        // 支付成功的订单发起的冲正交易，冲正失败
                        InAccInfo accInfo = new InAccInfo();
                        accInfo.setOrderId(bankOrder.getOrderId());
                        accInfo.setAmount(new BigDecimal(res.getTotal_fee()).divide(new BigDecimal(100)));
                        accInfo.setRetCode("01");
                        accInfo.setCardType(BankCardType.Unknown.toString());
                        checkOrderResult.setAccInfo(accInfo);
                        checkOrderResult.setBankFailure(true);
                        checkOrderResult.setErrMsg("小额免密查询返回冲正失败！");
                    } else {
                        bankOrderManager.updateSuccess(bankOrder, target);
                    }
                    logger.error("小额免密冲正订单：" + bankOrder.getOrderId() + ",原支付订单：" + oriBankOrder.getOrderId() + "，交易成功"
                            + "交易状态：" + tradeState + ",交易状态描述:" + res.getTrade_state_desc());
                }

            } else {
                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
                checkOrderResult.setErrMsg("系统返回对账结果为空");
                logger.error("冲正订单：" + bankOrder.getOrderId() + "，查询失败" + "err_code：" + res.getErr_code() + "。错误信息为："
                        + res.getErr_msg());
            }
        } else {
            checkOrderResult.setErrMsg("验签失败");
            logger.error("小额免密冲正订单：" + bankOrder.getOrderId() + "，验签失败" + "status：" + res.getStatus() + "。返回信息为："
                    + res.getMessage());
        }
        return checkOrderResult;

    }

    /**
     * 
     * 功能描述：退款订单对账
     *
     * @param result
     * @param bankOrder
     * @return
     * 
     * @author 宣广海
     *
     * @since 2016年10月14日
     *
     * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
     */
    public CheckOrderResult refundCheckOrder(Result result, BankOrder bankOrder) {

        CheckOrderResult checkOrderResult = new CheckOrderResult();
        checkOrderResult.setSuccess(false);
        if (result == null || !result.isSuccess()) {
            logger.error("refund bankClient fail.");
            if (result == null || ProcCodeConstants.PROC_CODE_100E6062.equals(result.getResultCode())) {
                BankCountDownLatch.failIncrease(bankOrder.getBankCode());
                checkOrderResult.setCommunicateError(true);
            }
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6062);
            checkOrderResult.setErrMsg("系统返回对账结果为空");
            return checkOrderResult;
        }
        MicroRefundQueryResMsg res = (MicroRefundQueryResMsg) result.getDefaultModel();
        if (res == null) {
            // 查询订单为空
            logger.error("fail:orderId:" + bankOrder.getOrderId() + " errcode:" + ProcCodeConstants.PROC_CODE_100E5062
                    + " err:bis refundQuery is null.");
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
            checkOrderResult.setErrMsg("银行返回对账结果为空");
            return checkOrderResult;
        }

        if (res.isSuccess()) {
            /**
             * result_code为0表示业务成功
             */
            if (MicroPayConstants.MICRO_RESULT_CODE_SUCCESS.equals(res.getResult_code())) {
                /**
                 * 支付成功,威富通会返回多笔退款交易
                 */
                int refundCount = res.getRefund_count();
                for (int i = 0; i < refundCount; i++) {
                    MicroRefundQueryResItem refundItem = res.getRefundItems().get(i);
                    if (refundItem.getOut_refund_no().equals(bankOrder.getOutOrderId())) {
                        String refundStatus = refundItem.getRefund_status();
                        if (MicroPayConstants.MICRO_REFUND_QUERY_SUCCESS.equals(refundStatus)) {
                            // 成功处理
                            checkOrderResult.setSuccess(true);
                            InAccInfo accInfo = new InAccInfo();
                            accInfo.setOrderId(bankOrder.getOrderId());
                            accInfo.setAmount(new BigDecimal(refundItem.getRefund_fee()).divide(new BigDecimal(100)));// 退款金额
                            accInfo.setRetCode("00");
                            accInfo.setCardType(BankCardType.Unknown.toString());
                            checkOrderResult.setAccInfo(accInfo);
                            logger.error(
                                    "小额免密支付refund订单：" + bankOrder.getOrderId() + "的交易银行处理成功。" + "退款状态：" + refundStatus);
                        } else if (MicroPayConstants.MICRO_REFUND_QUERY_FAIL.equals(refundStatus)) {
                            // 失败处理
                            checkOrderResult.setBankFailure(true);
                            InAccInfo accInfo = new InAccInfo();
                            accInfo.setOrderId(bankOrder.getOrderId());
                            accInfo.setAmount(new BigDecimal(refundItem.getRefund_fee()).divide(new BigDecimal(100)));
                            accInfo.setRetCode("01");
                            accInfo.setCardType(BankCardType.Unknown.toString());
                            checkOrderResult.setAccInfo(accInfo);
                            logger.error(
                                    "小额免密支付refund订单：" + bankOrder.getOrderId() + "的交易银行退款失败。" + "退款状态：" + refundStatus);
                            String errMsg = res.getMessage();
                            if (errMsg != null) {
                                checkOrderResult.setErrMsg(errMsg);
                            } else {
                                checkOrderResult.setErrMsg("银行返回退款交易失败。");
                            }
                        } else if (MicroPayConstants.MICRO_REFUND_QUERY_PROCESSING.equals(refundStatus)) {
                            logger.error(
                                    "小额免密支付refund订单：" + bankOrder.getOrderId() + "的退款交易进行中" + "退款状态：" + refundStatus);
                            String errMsg = res.getMessage();
                            if (errMsg != null) {
                                checkOrderResult.setErrMsg(errMsg);
                            } else {
                                checkOrderResult.setErrMsg("银行返回退款交易处理中.");
                            }
                        } else if (MicroPayConstants.MICRO_REFUND_QUERY_NOTSURE.equals(refundStatus)) {
                            if (bankOrder.getOrderStatus().equals(BankOrderStatus.ACCEPTED)) {
                                // 订单为已受理状态时，不允许修改
                                logger.error("小额免密支付refund订单：" + bankOrder.getOrderId() + "的退款交易不存在" + "退款状态："
                                        + refundStatus);
                                checkOrderResult.setErrMsg("订单为已受理状态，未发往银行，请耐心等待");
                            } else {
                                logger.error("小额免密支付refund订单：" + bankOrder.getOrderId() + "的退款交易不存在" + "退款状态："
                                        + refundStatus);
                                String errMsg = res.getErrMessage();
                                if (errMsg != null) {
                                    checkOrderResult.setErrMsg(errMsg);
                                } else {
                                    checkOrderResult.setErrMsg("银行返回退款交易不存在。");
                                }
                                // 查询订单不存在
                                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5041);
                            }
                        } else if (MicroPayConstants.MICRO_REFUND_QUERY_CHANGE.equals(refundStatus)) {
                            logger.error(
                                    "小额免密支付refund订单：" + bankOrder.getOrderId() + "的退款交易转入代发" + "退款状态：" + refundStatus);
                            String errMsg = res.getMessage();
                            if (errMsg != null) {
                                checkOrderResult.setErrMsg(errMsg);
                            } else {
                                checkOrderResult.setErrMsg("银行返回退款交易转入代发。");
                            }
                        }
                    }
                }
            } else {
                checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
                if (res.getErr_code().equals("Refund not exists")) {
                    if (bankOrder.getOrderStatus().equals(BankOrderStatus.ACCEPTED)) {
                        checkOrderResult.setErrMsg("系统返回对账结果为空,订单已受理，请耐心等待");
                    } else {
                        checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5041);
                        checkOrderResult.setErrMsg("系统返回对账结果为空");
                    }
                }
				if (res.getErr_code().equals("REFUND_FAIL")&&"已撤销".equals(res.getErr_msg())) {
					checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E5041);
					checkOrderResult.setErrMsg("退款已经撤销");
					logger.error("退款订单：" + bankOrder.getOrderId() + "，退款已经撤销,可以手工处理。" + "err_code：" + res.getErr_code() + "。错误信息为："
							+ res.getErr_msg());
				}
                logger.error("退款订单：" + bankOrder.getOrderId() + "，查询失败" + "err_code：" + res.getErr_code() + "。错误信息为："
                        + res.getMessage());
            }
        } else {
            checkOrderResult.setErrCode(ProcCodeConstants.PROC_CODE_100E6022);
            checkOrderResult.setErrMsg("小额免密返回验签失败");
            logger.error("小额免密退款订单：" + bankOrder.getOrderId() + "，验签失败" + "status：" + res.getStatus() + "。返回信息为："
                    + res.getMessage());
        }
        return checkOrderResult;
    }

    @Override
    public BankOrder getDbOrder() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public BaseMessage dayend(String bank_bus) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result getDayendMsg(String string) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<CheckOrderResult> checkDayend(String bank_bus) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public CheckOrderResult checkDayendOrder(BaseDayendEntry bdm, BankOrder bo) {
        // TODO Auto-generated method stub
        return null;
    }

}
